package com.stellar.wechat.core.auth;

import com.fasterxml.jackson.databind.JsonNode;
import com.stellar.wechat.config.WxMiniProgramConfig;
import com.stellar.wechat.core.common.AccessTokenUtil;
import com.stellar.wechat.core.common.WxHttpClient;
import com.stellar.wechat.core.common.exception.WxApiException;
import com.stellar.wechat.core.entity.WxSessionInfo;
import com.stellar.wechat.core.enums.WxErrorCode;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.HmacUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.util.UriComponentsBuilder;

import java.io.IOException;
import java.net.URI;
import java.net.URLEncoder;
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Collectors;


@Slf4j
@Service
public class WxAuthServiceImpl implements WxAuthService {

    private final WxMiniProgramConfig config;

    private final WxHttpClient wxHttpClient;

    private final AccessTokenUtil accessTokenUtil;

    public WxAuthServiceImpl(WxMiniProgramConfig config,
                             WxHttpClient wxHttpClient,
                             AccessTokenUtil accessTokenUtil) {
        this.config = config;
        this.wxHttpClient = wxHttpClient;
        this.accessTokenUtil = accessTokenUtil;
    }

    @Override
    public WxSessionInfo code2Session(String code) throws IOException, WxApiException {
        URI uri = UriComponentsBuilder.fromHttpUrl(config.getApiBaseUrl())
                .path("/sns/jscode2session")
                .queryParam("appid", config.getAppId())
                .queryParam("secret", config.getAppSecret())
                .queryParam("js_code", code)
                .queryParam("grant_type", "authorization_code")
                .build().toUri();


        return wxHttpClient.get(uri, WxSessionInfo.class);
    }

    @Override
    public boolean checkSessionKey(String sessionKey, String openid) throws WxApiException {
        try {
            String accessToken = accessTokenUtil.getAccessToken(true);

            // 编码 openid（用于签名）
            String encodedOpenid = URLEncoder.encode(openid, "UTF-8").replace("+", "%20");

            // 构建签名原始数据（按字典序排序）
            Map<String, String> params = new TreeMap<>();
            params.put("openid", encodedOpenid);
            String rawData = params.entrySet().stream()
                    .map(entry -> entry.getKey() + "=" + entry.getValue())
                    .collect(Collectors.joining("&"));

            // 生成签名（使用解码后的 sessionKey）
//            String signature = HmacUtils.hmacSha256Hex(sessionKey, rawData);
//
//            // 编码签名（用于URL）
//            String encodedSignature = URLEncoder.encode(signature, "UTF-8").replace("+", "%20");

            String signature = HmacUtils.hmacSha256Hex(sessionKey, "");

            // 构建请求 URL
            URI uri = URI.create(String.format("%s/wxa/checksession?access_token=%s&openid=%s&signature=%s&sig_method=hmac_sha256",
                    config.getApiBaseUrl(),
                    accessToken,
                    openid,
                    signature));

            // 调试输出
            System.out.println("【调试信息】");
            System.out.println("SessionKey: " + sessionKey);
            System.out.println("RawData: " + rawData);
            System.out.println("Signature: " + signature);
            System.out.println("Request URL: " + uri);


            JsonNode response = wxHttpClient.get(uri, JsonNode.class);
            return response.get("errcode").asInt() == 0;
        } catch (IOException e) {
            throw new WxApiException(WxErrorCode.NETWORK_ERROR);
        }
    }

    @Override
    public WxSessionInfo resetUserSessionKey(String openid, String sessionKey) throws WxApiException {
        try {
            String accessToken = accessTokenUtil.getAccessToken(false);

            // 编码 openid（用于签名）
            String encodedOpenid = URLEncoder.encode(openid, "UTF-8").replace("+", "%20");

//            // 构建签名原始数据（按字典序排序）
//            Map<String, String> params = new TreeMap<>();
//            params.put("openid", encodedOpenid);
//            String rawData = params.entrySet().stream()
//                    .map(entry -> entry.getKey() + "=" + entry.getValue())
//                    .collect(Collectors.joining("&"));

            // 生成签名（使用解码后的 sessionKey）
            String signature = HmacUtils.hmacSha256Hex(sessionKey, "");


            URI uri = URI.create(String.format("%s/wxa/resetusersessionkey?access_token=%s&openid=%s&signature=%s&sig_method=hmac_sha256",
                    config.getApiBaseUrl(),
                    accessToken,
                    URLEncoder.encode(openid, "UTF-8"),
                    URLEncoder.encode(signature, "UTF-8")
            ));
            return wxHttpClient.get(uri, WxSessionInfo.class);
        } catch (IOException e) {
            throw new WxApiException(WxErrorCode.NETWORK_ERROR);
        }
    }


}